﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using CSharp_Remote_Control.Enum;
using Newtonsoft.Json;
using CSharp_Remote_Control.Model;

namespace CSharp_Remote_Control.Utils
{
    internal class TCPServer
    {
        public string? EnumState { get; set; }

        public bool IsRunning = false;

        Thread HandleClientMsgThread;
        Thread HandleAcceptTcpClientThread;

        TcpListener Listener;

        // 创建锁对象
        static object lockObject = new object();

        public delegate void OnServerStartDelegate(int port);
        public event OnServerStartDelegate? OnServerStartEvent;

        public delegate void OnServerCloseDelegate();
        public event OnServerCloseDelegate? OnServerCloseEvent;

        public delegate void OnServerMsgDelegate(String? msg);
        public event OnServerMsgDelegate? OnServerMsgEvent;

        public delegate void OnServerMsgJsonDelegate(String? msg, TcpClient client);
        public event OnServerMsgJsonDelegate? OnServerMsgJsonEvent;

        public delegate void OnClientConnectDelegate(String? ip, int? port, TcpClient client);
        public event OnClientConnectDelegate? OnClientConnectEvent;


        private volatile static TCPServer? singleton;

        private TCPServer() { }


        public static TCPServer getInstance()
        {
            if (singleton == null)
            {
                lock (lockObject)
                {
                    if (singleton == null)
                    {
                        singleton = new TCPServer();
                    }
                }
            }
            return singleton;
        }


        public void Open(int port = 5000)
        {
            this.IsRunning = true;
            Listener = new TcpListener(IPAddress.Any, port);
            Listener.Start();

            OnServerStartEvent?.Invoke(port);
            EnumState = Enum.EnumState.OPENED;

            // 线程内操作无限循环
            HandleAcceptTcpClientThread = new Thread((q) =>
            {
                // 不停循环获取Tcp客户端连接
                while (IsRunning)
                {

                    if (!Listener.Pending())
                    {
                        //为了避免每次都被tcpListener.AcceptTcpClient()阻塞线程，添加了此判断，
                        //no connection requests have arrived。
                        //当没有连接请求时，什么也不做，有了请求再执行到tcpListener.AcceptTcpClient()
                    }
                    else
                    {
                        // 获取客户端连接, 此处会卡住
                        TcpClient client = Listener.AcceptTcpClient();

                        // 获取客户端IP和对接端口
                        IPEndPoint? iPEndPoint = (IPEndPoint?)client.Client.RemoteEndPoint;

                        // 触发获取客户端事件
                        OnClientConnectEvent?.Invoke(
                            iPEndPoint?.Address?.ToString(),
                            iPEndPoint?.Port,
                            client
                            );
                        HandleClientMsgThread = new Thread(HandleClientMsg);
                        HandleClientMsgThread.Start(client);
                    }



                }

            });
            HandleAcceptTcpClientThread.Start();
        }


        /// <summary>
        /// 处理客户端消息
        /// </summary>
        /// <param name="obj"></param>
        void HandleClientMsg(object obj)
        {
            TcpClient client = (TcpClient)obj;

            NetworkStream stream = client.GetStream();
            byte[] buffer = new byte[1024];
            int bytesRead;


            try
            {
                string message = "";
                string jsonStr = "";
                // 读取数据同时回显数据
                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    OnServerMsgEvent?.Invoke(message);


                    //Debug.WriteLine(message);
                    //解析分批数据
                    if (message == MsgUtil.getBegin())
                    {
                        message = "";
                        jsonStr = "";
                    }
                    else if (message == MsgUtil.getEnd())
                    {
                        // 获取到完整数据
                        OnServerMsgJsonEvent?.Invoke(jsonStr.Trim('|'), client);
                        // 回显数据给对应的客户端
                        byte[] response = Encoding.UTF8.GetBytes(
                            MsgUtil.TCPMsgWrap(
                                JsonConvert.SerializeObject(new TransformModel()
                                {
                                    DataBase64 = "server receive", // UTF8中文字符占2字节
                                    Type = Enum.EnumState.TCP_TEXT
                                })
                                )
                            );
                        stream.Write(response, 0, response.Length);

                        message = "";
                        jsonStr = "";
                    }
                    else
                    {
                        jsonStr += message;
                    }


                }
                Debug.WriteLine("读取完毕");
            }
            catch (Exception ex)
            {
                Console.WriteLine("客户端异常: " + ex.Message);
            }
            finally
            {
                client.Close();
                Debug.WriteLine("客户端断开连接");
            }
        }

        /// <summary>
        /// TODO: 这里无法直接调用封装的TCPClient
        /// </summary>
        public void Close()
        {
            StaticItem.Clients.ForEach(x =>
            {
                x.Close();
            });

            IsRunning = false;
            HandleClientMsgThread?.Interrupt();
            HandleAcceptTcpClientThread?.Interrupt();
            Listener?.Stop();
        }


    }
}
